/**
 @author MAMAMA
 @date 2019-07-12
 @description control panasonic dc motor
*/

#ifndef _KINCO_MOTOR_H_
#define _KINCO_MOTOR_H_

#include "Stream.h"
#include "stm32f10x_it.h"
#include "ModbusMaster.h"

#define EncoderResolution 10000.0f
#define KincoMaxTurn 429496.7296

/**
modbus coils
*/
#define MODBUS_ALM_STATE 0x00A1

/**
 modbus address 1000h group
*/
#define DEVICE_INFO 0x1000
#define DEVICE_NAME 0x564D //设备名称应当是该值

/* 3100 控制字 */
#define CONTROL_WORD          0x3100
#define KINCO_POWERON         0x000F
#define KINCO_POWEROFF        0x0006

/* 3200 状态字*/
#define STATUS_WORD          0x3200

/* 6F00 目标速度, 32bit */
#define TARGET_SPEED         0x6F00

#define TORQUELIMIT          0x301A

/* 实际速度，32位 */
#define ACTUAL_VEL          0x3B00
/* 实际位置 32位 */
#define ACTUAL_POS          0x3700
#define CLEARALARM          0x4102
#define CLEARALARM_CMD      0x7274

#pragma pack(push)     /* save origin value */
#pragma pack(1)

typedef union{
    struct{ 
        uint16_t low;
        uint16_t high;
    }words;
    int32_t vel;
} KincoVel_T;

typedef union{
    struct{ 
        uint16_t low;
        uint16_t high;
    }words;
    int32_t pos;
} KincoPos_T;

#pragma pack(pop)  /* restore origin value */


class KincoMotor
{
private:
    ModbusMaster* _pmodbus_master;
    Stream* _pstream;
    static const uint16_t _max_velocity = 3000;
    short _vel_cmd_val;
    enum ConnectState
    {
        OFFLINE = 0,
        ONLINE,
        ALARM            //电机报警
    }_connect_state;
    uint16_t status;     //状态字
    
public:
    KincoMotor(uint8_t axisid, Stream* pstream);
    ~KincoMotor(void);    
    uint8_t axis_id;    //device address in modbus rtu protocol
    uint32_t actual_pos;
    double init_turns;
    double last_turns;
    bool initModbus(void);
    bool isOnline(void)
    {
        return (_connect_state != OFFLINE);
    }
    bool powerOnOff(bool on_off);      //使能电机
    bool setVeloctiy(short vel);
    bool setTorqueLimit(unsigned short limit);
    uint16_t getTorqueLimit(void);
    void disconnectMotor(void);
    short getMotorCommandVel(void){return _vel_cmd_val;}
    double getMotorActualVel(void);
    bool getMotorActualPos(void);
    bool connectOnce(void);
    uint8_t getAlarmState(void);
    uint8_t clearAlarm(void);
};

#endif
